import RVOMath from "./rvo/RVOMath";
import Simulator from "./rvo/Simulator";
import Vector2D from "./rvo/Vector2D";

export default class GameMgr1 {
	private simulator: Simulator;
	agentCnt = 10;
	space = 15;
	speed = 60;
	mSpheres: Laya.Sprite[] = [];

	constructor() {
		this.simulator = new Simulator();
		this.start();
		this.onEnable();
		Laya.timer.frameLoop(1, this, this.update);
	}

	onEnable() {
		Laya.stage.on(Laya.Event.MOUSE_DOWN, this, this.onMouseDown);
		Laya.stage.on(Laya.Event.MOUSE_UP, this, this.onMouseUp);
		Laya.stage.on(Laya.Event.MOUSE_WHEEL, this, this.onMouseWheel);
	}

	onDisable() {
		Laya.stage.off(Laya.Event.MOUSE_DOWN, this, this.onMouseDown);
		Laya.stage.off(Laya.Event.MOUSE_UP, this, this.onMouseUp);
	}

	start() {
		this.addObstacle();
		this.simulator.processObstacles();

		this.simulator.setAgentDefaults(
			5,
			4,
			1,
			0.1,
			5,
			this.speed,
			new Vector2D(0, 0)
		);
		this.createAgent(new Vector2D(10, 10), "blue", 5);
		this.createAgent(new Vector2D(500, 10), "red", 5);
		this.createGameObject(new Vector2D(300, 400), "yellow", 50);
	}

	addObstacle() {
		let obstacle1: Vector2D[] = [];
		obstacle1.push(new Vector2D(-10.0, 40.0));
		obstacle1.push(new Vector2D(-80.0, 40.0));
		obstacle1.push(new Vector2D(-80.0, 10.0));
		obstacle1.push(new Vector2D(-10.0, 10.0));
		this.simulator.addObstacle(obstacle1);

		let sp1 = new Laya.Sprite();
		sp1.graphics.drawPoly(
			300,
			300,
			[-10.0, 40.0, -80.0, 40.0, -80.0, 10.0, -10.0, 10.0],
			"#FF7F50"
		);
		Laya.stage.addChild(sp1);

		let obstacle2: Vector2D[] = [];
		obstacle2.push(new Vector2D(50.0, 60.0));
		obstacle2.push(new Vector2D(30.0, 30.0));
		obstacle2.push(new Vector2D(50.0, -10.0));
		obstacle2.push(new Vector2D(80.0, 20.0));
		obstacle2.push(new Vector2D(70.0, 60.0));
		this.simulator.addObstacle(obstacle2);

		let sp2 = new Laya.Sprite();
		sp2.graphics.drawPoly(
			0,
			0,
			[50.0, 60.0, 30.0, 30.0, 50.0, -10.0, 80.0, 20.0, 70.0, 60.0],
			"#FF7F50"
		);
		Laya.stage.addChild(sp2);
	}

	onMouseDown(event: Event) {
		let index = 0;
		let x = Laya.stage.mouseX;
		let y = Laya.stage.mouseY;
		for (let i = 0; i < this.agentCnt; i++) {
			// let j = 0;
			for (let j = 0; j < this.agentCnt; j++) {
				let p = this.simulator.getGoal(index++);
				// p.x = i * this.space + x;
				// p.y = j * this.space + y;
				p.x = x;
				p.y = y;
			}
		}
	}

	onMouseUp(event: Event) {
		let x = Laya.stage.mouseX;
		let y = Laya.stage.mouseY;
		let index = this.agentCnt * this.agentCnt;
		for (let i = 0; i < this.agentCnt; i++) {
			for (let j = 0; j < this.agentCnt; j++) {
				let p = this.simulator.getGoal(index++);
				p.x = i * this.space + x;
				p.y = j * this.space + y;
			}
		}
	}

	onMouseWheel(event: Event) {
		let x = Laya.stage.mouseX;
		let y = Laya.stage.mouseY;
		let index = this.agentCnt * this.agentCnt * 2;
		let p = this.simulator.getGoal(index++);
		p.x = x;
		p.y = y;
	}

	createAgent(pos: Vector2D, fillColor: any, radius: number) {
		let cnt = this.agentCnt;
		for (let i = 0; i < cnt; i++) {
			// let j = 0;
			for (let j = 0; j < cnt; j++) {
				let p = new Vector2D(
					i * this.space + pos.x + radius * i,
					j * this.space + pos.y + radius * j
				);
				this.createGameObject(p, fillColor, radius);
			}
		}
	}

	createGameObject(position: Vector2D, fillColor: any, radius: number) {
		let idx = this.simulator.addAgent(position, radius);
		let node = new Laya.Sprite();
		node.graphics.drawCircle(0, 0, radius, fillColor);
		this.mSpheres.push(node);
		node.pos(position.x, position.y);
		Laya.stage.addChild(node);
	}

	setPreferredVelocities() {
		let agentCnt = this.simulator.getNumAgents();
		for (let i = 0; i < agentCnt; i++) {
			let agentPos = this.simulator.getAgentPosition(i);
			let agentGoal = this.simulator.getGoal(i);
			let goalVector = agentGoal.minus(agentPos);
			let disSqr = RVOMath.absSq(goalVector);
			if (i == 0) {
				console.log(agentGoal, agentPos, disSqr);
			}
			// stop
			if (disSqr < RVOMath.RVO_EPSILON) {
				// Agent is within one radius of its goal, set preferred velocity to zero
				this.simulator.setAgentPrefVelocity(i, new Vector2D(0.0, 0.0));
				continue;
			}
			if (disSqr > 1.0) {
				goalVector = RVOMath.normalize(goalVector).scale(this.speed);
			} else {
				goalVector = RVOMath.normalize(goalVector).scale(this.speed * 0.01);
			}
			this.simulator.setAgentPrefVelocity(i, goalVector.scale(0.1));
			// let angle = Math.random() * 2.0 * Math.PI;
			// let dist = Math.random() * 0.0001;
			// Simulator.instance.setAgentPrefVelocity(
			// 	i,
			// 	agentPos.plus(
			// 		new Vector2(Math.cos(angle), Math.sin(angle)).scale(dist)
			// 	)
			// );
		}
	}

	update() {
		let dt = Laya.timer.delta;
		dt = Math.min(dt, 33);
		// 更新逻辑坐标
		this.setPreferredVelocities();
		this.simulator.run(dt);
		// 更新渲染坐标
		for (let i = 0; i < this.simulator.getNumAgents(); i++) {
			let p = this.simulator.getAgentPosition(i);
			this.mSpheres[i].pos(p.x, p.y);
		}
	}
}
